package client.logic.chat;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.PublicKey;

import packets.Packet;
import packets.server.Certificate;

import encription.SecurityHandler;
import exceptions.PacketTooBigException;

/**
 * a class that is used to send messages to a foreign client
 */
public class ChatSender{
	Socket _sock;
	String _myname;
	PublicKey _key;
	BufferedOutputStream _out;

	/**
	 * Creates an instance of ChatSender
	 * @param sock the socket which the chat sender communicates with
	 * @param name the name of the messages sender (the current logged in user)
	 * @param key the key to encrypt the sent messages with
	 */
	public ChatSender(Socket sock , String name, PublicKey key){
		_sock = sock;
		_myname = name;
		_key = key;
	}

	/**
	 * Initialize the message sender (for a chat starter)
	 * @param cf the Certificate to send to the other client
	 */
	public void init(Certificate cf){
		try {
			_out = new BufferedOutputStream(_sock.getOutputStream()); //initialize output stream
			byte[] b = SecurityHandler.encrypt(SecurityHandler.getBytes(new Packet(cf)), _key); //encrypt and send the certificate to the other client
			_out.write(b);
			_out.flush();
		} catch (Exception e) {
			SecurityHandler.catchException("initializing chat sender", e, true);
			//e.printStackTrace();
		}
	}

	/**
	 * Initializes the message sender without a certificate (for a chat waiter)
	 */
	public void init(){
		try {
			_out = new BufferedOutputStream(_sock.getOutputStream()); //initialize output stream
		} catch (IOException e) {
			SecurityHandler.catchException("initializing chat", e, true);
			//e.printStackTrace();
		}
	}

	/**
	 * sends a message to the foreign client
	 * @param message the message to send
	 */
	public void sendMessage(String message){
		try {
			Packet pac = new Packet(_myname + "> "+message);			//creates packet to send
			byte[] text = SecurityHandler.getBytes(pac);				//serializes the packet
			byte[] encryptText = SecurityHandler.encrypt(text,_key);	//encrypts the packet with the public key
			if (encryptText.length > 2048){
				throw new PacketTooBigException("cant send more then 2048 bytes");
			}else{
				_out.write(encryptText);								//sends the encrypted packet
				_out.flush();
			}
		}catch(Exception e){
			SecurityHandler.catchException("sending a chat message", e, true);
		}
	}

	/**
	 * closes the message sending channel by sending a null message
	 */
	public void close(){
		try {
			byte[] text = SecurityHandler.getBytes(new Packet((String)null));	//serialize a null message
			byte[] encryptText = SecurityHandler.encrypt(text,_key);			//encrypts the message
			_out.write(encryptText);											//sends the message
			_out.close();
		} catch (Exception e) {
			SecurityHandler.catchException("closing chat", e, true);
			//e.printStackTrace();
		}
	}
}
